//
// Created by twetec on 25-8-17.
//

#include "handle_sqlserver_probe_task.h"

#include <boost/json.hpp>
#include <sybdb.h>

#include <bs_thread_pool/BS_thread_pool.hpp>

#include <network_prober/utils/constants.h>


using namespace std::chrono_literals;

namespace network_prober::probe
{
// 线程池
static BS::thread_pool s_iopool{1000};

/**
 * 数据库错误处理
 */
static int s_dbErrHandler(DBPROCESS* dbproc, int severity, int dberr, int oserr, char* dberrstr, char* oserrstr)
{
    return INT_CANCEL; // 改为返回1允许继续执行
}

/**
 * 数据库消息处理
 */
static int s_dbMsgHandler(DBPROCESS * dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *proc, int line)
{
    return INT_CANCEL; // 改为返回1允许继续执行
}

// SQLServerProbeIPv4::SQLServerProbeIPv4(
//     std::string_view interface,
//     std::string_view target,
//     std::uint32_t port,
//     std::string_view userName,
//     std::string_view password,
//     std::string_view databaseName,
//     std::string_view queryStatement
// )
// : m_interface(interface), m_target(target), m_port(port), m_userName(userName),
// m_password(password), m_databaseName(databaseName), m_queryStatement(queryStatement)
// {
//     // 初始化libmongoc库，在应用程序启动时，只调用一次
//     std::call_once(utils::g_sqlServerClientInitOnceFlag, [] {
//         // 初始化正常
//         dbinit();
//     });
// }
//
// void SQLServerProbeIPv4::setOnProbedCallback(std::function<void(std::int64_t)> callback)
// {
//     m_onProbedCallback = std::move(callback);
// }
//
// void SQLServerProbeIPv4::probe()
// {
//     // 建立连接时，开始计时
//     m_probeStartTime = std::chrono::steady_clock::now();
//
//     // 指向当前对象的shared_ptr
//     auto self{shared_from_this()};
//
//     // 发起探测
//     m_onProbedCallbackFuture = std::async(std::launch::async, [this, self] {
//          // 初始化db库
//         // if (dbinit() == FAIL) {
//         //     // 错误信息
//         //     SPDLOG_INFO("SQLServer驱动初始化失败..");
//         //     // 回调结果
//         //     m_onProbedCallback(-1);
//         //     // 结束执行
//         //     return;
//         // }
//
//         // 设置错误执行方式，避免程序退出
//         dberrhandle(s_dbErrHandler);
//         // 消息处理，避免程序退出
//         dbmsghandle(s_dbMsgHandler);
//
//         // 创建登录对象
//         LOGINREC* login = dblogin();
//         if (login == nullptr) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer的login对象初始化失败..");
//             // 回收资源
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 设定连接账号
//         DBSETLUSER(login, m_userName.c_str());
//         // 设定连接密码
//         DBSETLPWD(login, m_password.c_str());
//
//         // 设置登录超时时间(秒)
//         dbsetlogintime(10);
//         // 设置查询超时时间
//         dbsettime(10);
//
//         // 连接数据库服务器
//         DBPROCESS* dbproc = dbopen(login, (m_target + ":" + std::to_string(m_port)).c_str());
//         if (dbproc == nullptr) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标连接失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 切换到指定数据库
//         if (dbuse(dbproc, m_databaseName.c_str()) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标数据库切换失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 构建SQL语句
//         const char* sql = m_queryStatement.empty()? "SELECT 1" : m_queryStatement.c_str();
//
//         // 提交sql命令
//         if (dbcmd(dbproc, sql) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标sql命令提交失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//              m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 执行sql命令
//         if (dbsqlexec(dbproc) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标sql命令执行失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 回收资源
//         dbclose(dbproc);
//         dbloginfree(login);
//         // dbexit();
//
//         // 回调结果
//         m_onProbedCallback(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//     });
// }
//
// SQLServerProbeIPv4::~SQLServerProbeIPv4()
// {
//
// }

HandleSQLServerProbeIPv4Awaiter::HandleSQLServerProbeIPv4Awaiter(const database::ProbeTaskModel &probeTask)
: m_interface(probeTask.interface), m_target(probeTask.address), m_port(probeTask.port), m_userName(probeTask.userName),
m_password(probeTask.password), m_databaseName(probeTask.databaseName), m_queryStatement(probeTask.queryStatement)
{
    // 初始化libmongoc库，在应用程序启动时，只调用一次
    std::call_once(utils::g_sqlServerClientInitOnceFlag, [] {
        // 初始化正常
        dbinit();
    });
}

bool HandleSQLServerProbeIPv4Awaiter::await_ready()
{
    return false;
}

void HandleSQLServerProbeIPv4Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    s_iopool.submit_task([this, handle] {
        // 线程锁
        std::mutex mtx;
        std::condition_variable cv;

        // 请求计时 - 开始时间
        std::chrono::time_point<std::chrono::steady_clock> probeStartTime = std::chrono::steady_clock::now();

        // 发起探测
        std::future future = std::async(std::launch::async, [this, &probeStartTime, &mtx, &cv] {
            // 初始化db库
            // if (dbinit() == FAIL) {
            //     // 错误信息
            //     SPDLOG_INFO("SQLServer驱动初始化失败..");
            //     // 回调结果
            //     m_onProbedCallback(-1);
            //     // 结束执行
            //     return;
            // }

            // 设置错误执行方式，避免程序退出
            dberrhandle(s_dbErrHandler);
            // 消息处理，避免程序退出
            dbmsghandle(s_dbMsgHandler);

            // 创建登录对象
            LOGINREC* login = dblogin();
            if (login == nullptr) {
                // 错误信息
                SPDLOG_INFO("SQLServer的login对象初始化失败..");
                // 回收资源
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 设定连接账号
            DBSETLUSER(login, m_userName.c_str());
            // 设定连接密码
            DBSETLPWD(login, m_password.c_str());

            // 设置登录超时时间(秒)
            dbsetlogintime(6);
            // 设置查询超时时间
            dbsettime(6);

            // 连接数据库服务器
            DBPROCESS* dbproc = dbopen(login, (m_target + ":" + std::to_string(m_port)).c_str());
            if (dbproc == nullptr) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标连接失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 切换到指定数据库
            if (dbuse(dbproc, m_databaseName.c_str()) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标数据库切换失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 构建SQL语句
            const char* sql = m_queryStatement.empty()? "SELECT 1" : m_queryStatement.c_str();

            // 提交sql命令
            if (dbcmd(dbproc, sql) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标sql命令提交失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 执行sql命令
            if (dbsqlexec(dbproc) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标sql命令执行失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 回收资源
            dbclose(dbproc);
            dbloginfree(login);
            // dbexit();

            // 回调结果
            // 加锁
            std::unique_lock<std::mutex> lock(mtx);
            // 保存延迟
            m_delay = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - probeStartTime).count();
            // 通知延迟保存成功
            cv.notify_one();
        });

        // 等待响应（12s）
        std::unique_lock<std::mutex> lock(mtx);
        std::cv_status cvStatus = cv.wait_for(lock, 8s);

        // 如果等待超时,则将延迟置为-1
        if (cvStatus == std::cv_status::timeout) m_delay = -1;

        // 恢复暂停的协程
        handle.resume();
    });
}

std::int64_t HandleSQLServerProbeIPv4Awaiter::await_resume()
{
    return m_delay;
}


// SQLServerProbeIPv6::SQLServerProbeIPv6(
//     std::string_view interface,
//     std::string_view target,
//     std::uint32_t port,
//     std::string_view userName,
//     std::string_view password,
//     std::string_view databaseName,
//     std::string_view queryStatement
// )
// : m_interface(interface), m_target(target), m_port(port), m_userName(userName),
// m_password(password), m_databaseName(databaseName), m_queryStatement(queryStatement)
// {
//     // 初始化libmongoc库，在应用程序启动时，只调用一次
//     std::call_once(utils::g_sqlServerClientInitOnceFlag, [] {
//         // 初始化正常
//         dbinit();
//     });
// }
//
// void SQLServerProbeIPv6::setOnProbedCallback(std::function<void(std::int64_t)> callback)
// {
//     m_onProbedCallback = std::move(callback);
// }
//
// void SQLServerProbeIPv6::probe()
// {
//     // 建立连接时，开始计时
//     m_probeStartTime = std::chrono::steady_clock::now();
//
//     // 指向当前对象的shared_ptr
//     auto self{shared_from_this()};
//
//     // 发起探测
//     m_onProbedCallbackFuture = std::async(std::launch::async, [this, self] {
//         // 初始化db库
//         // if (dbinit() == FAIL) {
//         //     // 错误信息
//         //     SPDLOG_INFO("SQLServer驱动初始化失败..");
//         //     // 回调结果
//         //     m_onProbedCallback(-1);
//         //     // 结束执行
//         //     return;
//         // }
//
//         // 设置错误执行方式，避免程序退出
//         dberrhandle(s_dbErrHandler);
//         // 消息处理，避免程序退出
//         dbmsghandle(s_dbMsgHandler);
//
//         // 创建登录对象
//         LOGINREC* login = dblogin();
//         if (login == nullptr) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer的login对象初始化失败..");
//             // 回收资源
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 设定连接账号
//         DBSETLUSER(login, m_userName.c_str());
//         // 设定连接密码
//         DBSETLPWD(login, m_password.c_str());
//
//         // 设置登录超时时间(秒)
//         dbsetlogintime(10);
//         // 设置查询超时时间
//         dbsettime(10);
//
//         // 连接数据库服务器
//         DBPROCESS* dbproc = dbopen(login, (m_target + ":" + std::to_string(m_port)).c_str());
//         if (dbproc == nullptr) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标连接失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 切换到指定数据库
//         if (dbuse(dbproc, m_databaseName.c_str()) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标数据库切换失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 构建SQL语句
//         const char* sql = m_queryStatement.empty()? "SELECT 1" : m_queryStatement.c_str();
//
//         // 提交sql命令
//         if (dbcmd(dbproc, sql) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标sql命令提交失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//              m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 执行sql命令
//         if (dbsqlexec(dbproc) == FAIL) {
//             // 错误信息
//             SPDLOG_INFO("SQLServer观测目标sql命令执行失败..");
//             // 回收资源
//             dbclose(dbproc);
//             dbloginfree(login);
//             // dbexit();
//             // 回调结果
//             m_onProbedCallback(-1);
//             // 结束执行
//             return;
//         }
//
//         // 回收资源
//         dbclose(dbproc);
//         dbloginfree(login);
//         // dbexit();
//
//         // 回调结果
//         m_onProbedCallback(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//     });
// }
//
// SQLServerProbeIPv6::~SQLServerProbeIPv6()
// {
// }

HandleSQLServerProbeIPv6Awaiter::HandleSQLServerProbeIPv6Awaiter(const database::ProbeTaskModel &probeTask)
: m_interface(probeTask.interface), m_target(probeTask.address), m_port(probeTask.port), m_userName(probeTask.userName),
m_password(probeTask.password), m_databaseName(probeTask.databaseName), m_queryStatement(probeTask.queryStatement)
{
    // 初始化libmongoc库，在应用程序启动时，只调用一次
    std::call_once(utils::g_sqlServerClientInitOnceFlag, [] {
        // 初始化正常
        dbinit();
    });
}

bool HandleSQLServerProbeIPv6Awaiter::await_ready()
{
    return false;
}

void HandleSQLServerProbeIPv6Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    s_iopool.submit_task([this, handle] {
        // 线程锁
        std::mutex mtx;
        std::condition_variable cv;

        // 请求计时 - 开始时间
        std::chrono::time_point<std::chrono::steady_clock> probeStartTime = std::chrono::steady_clock::now();

        std::future future = std::async(std::launch::async, [this, &probeStartTime, &mtx, &cv] {
                // 初始化db库
            // if (dbinit() == FAIL) {
            //     // 错误信息
            //     SPDLOG_INFO("SQLServer驱动初始化失败..");
            //     // 回调结果
            //     m_onProbedCallback(-1);
            //     // 结束执行
            //     return;
            // }

            // 设置错误执行方式，避免程序退出
            dberrhandle(s_dbErrHandler);
            // 消息处理，避免程序退出
            dbmsghandle(s_dbMsgHandler);

            // 创建登录对象
            LOGINREC* login = dblogin();
            if (login == nullptr) {
                // 错误信息
                SPDLOG_INFO("SQLServer的login对象初始化失败..");
                // 回收资源
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 设定连接账号
            DBSETLUSER(login, m_userName.c_str());
            // 设定连接密码
            DBSETLPWD(login, m_password.c_str());

            // 设置登录超时时间(秒)
            dbsetlogintime(6);
            // 设置查询超时时间
            dbsettime(6);

            // 连接数据库服务器
            DBPROCESS* dbproc = dbopen(login, (m_target + ":" + std::to_string(m_port)).c_str());
            if (dbproc == nullptr) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标连接失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 切换到指定数据库
            if (dbuse(dbproc, m_databaseName.c_str()) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标数据库切换失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 构建SQL语句
            const char *sql = m_queryStatement.empty() ? "SELECT 1" : m_queryStatement.c_str();

            // 提交sql命令
            if (dbcmd(dbproc, sql) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标sql命令提交失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 执行sql命令
            if (dbsqlexec(dbproc) == FAIL) {
                // 错误信息
                SPDLOG_INFO("SQLServer观测目标sql命令执行失败..");
                // 回收资源
                dbclose(dbproc);
                dbloginfree(login);
                // dbexit();
                // 加锁
                std::unique_lock<std::mutex> lock(mtx);
                // 保存延迟
                m_delay = -1;
                // 通知延迟保存成功
                cv.notify_one();
                // 结束执行
                return;
            }

            // 回收资源
            dbclose(dbproc);
            dbloginfree(login);
            // dbexit();

            // 回调结果
            // 加锁
            std::unique_lock<std::mutex> lock(mtx);
            // 保存延迟
            m_delay = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - probeStartTime).count();
            // 通知延迟保存成功
            cv.notify_one();
        });

        // 等待响应（12s）
        std::unique_lock<std::mutex> lock(mtx);
        std::cv_status cvStatus = cv.wait_for(lock, 8s);

        // 如果等待超时,则将延迟置为-1
        if (cvStatus == std::cv_status::timeout) m_delay = -1;

        // 恢复暂停的协程
        handle.resume();
    });
}

std::int64_t HandleSQLServerProbeIPv6Awaiter::await_resume()
{
    return m_delay;
}

}